
package com.github.lanif.sys.core.jwt;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.github.lanif.core.context.constant.ConstantContextHolder;
import io.jsonwebtoken.*;

import java.util.Date;

/**
 * JwtToken工具类
 *
 * @author
 * @date 2020/3/12 17:39
 */
public class JwtTokenUtil {

    /**
     * 生成token，使用配置的时间
     *
     * @author
     * @date 2020/3/12 17:52
     */
    public static String generateToken(JwtPayLoad jwtPayLoad) {
        return generateToken(jwtPayLoad,
                Convert.toInt(ConstantContextHolder.getTokenExpireSec()) * 1000);
    }

    /**
     * 生成token
     * @param jwtPayLoad
     * @param offset 希望多长时间后到期的毫秒值
     */
    public static String generateToken(JwtPayLoad jwtPayLoad, Integer offset) {
        DateTime expirationDate = DateUtil.offsetMillisecond(new Date(), offset);
        return Jwts.builder()
                .setClaims(BeanUtil.beanToMap(jwtPayLoad))
                .setSubject(jwtPayLoad.getUserId().toString())
                .setIssuedAt(new Date())
                .setExpiration(expirationDate)
                .signWith(SignatureAlgorithm.HS512, ConstantContextHolder.getJwtSecret())
                .compact();
    }

    /**
     * 根据token获取Claims
     *
     * @author
     * @date 2020/3/13 10:29
     */
    private static Claims getClaimsFromToken(String token) {
        return Jwts.parser()
                .setSigningKey(ConstantContextHolder.getJwtSecret())
                .parseClaimsJws(token)
                .getBody();
    }

    /**
     * 获取JwtPayLoad部分
     *
     * @author
     * @date 2020/3/12 17:53
     */
    public static JwtPayLoad getJwtPayLoad(String token) {
        Claims claims = getClaimsFromToken(token);
        return BeanUtil.mapToBean(claims, JwtPayLoad.class, false);
    }

    /**
     * 校验token是否正确
     *
     * @author
     * @date 2020/3/13 10:36
     */
    public static Boolean checkToken(String token) {
        try {
            getClaimsFromToken(token);
            return true;
        } catch (JwtException jwtException) {
            return false;
        }
    }

    /**
     * 校验token是否失效
     *
     * @author
     * @date 2020/3/13 10:30
     */
    public static Boolean isTokenExpired(String token) {
        try {
            Claims claims = getClaimsFromToken(token);
            final Date expiration = claims.getExpiration();
            return expiration.before(new Date());
        } catch (ExpiredJwtException expiredJwtException) {
            return true;
        }
    }

    /**
     * 检查如果失效时间在1小时内，则视为token将要过期
     * @param token
     * @return
     */
    public static Boolean isTokenWillExpire(String token) {
        try {
            Claims claims = getClaimsFromToken(token);
            final Date expiration = claims.getExpiration();

            Long duration = expiration.getTime() - new Date().getTime();
            return duration < 1 * 60 * 60 * 1000;
        } catch (ExpiredJwtException expiredJwtException) {
            return true;
        }
    }
}
